<?php

namespace app\model;

use app\controller\api\Station;
use think\facade\Db;
use think\helper\Str;
use think\Model;
use think\model\relation\HasMany;
use think\model\relation\HasOne;

class StationBasic extends Model
{
    public function saveData(): array
    {
        $param = request()->param();
        $this->startTrans();
        if (!empty($param['basic']['service_time'])) $param['basic']['service_time'] = implode("-", $param['basic']['service_time']);
        $param['basic']['address_location'] = Db::raw("ST_GeomFromText('POINT({$param['basic']['lng']} {$param['basic']['lat']})')");
        $param['basic']['active_tip'] = implode(",", $param['basic']['active_tip']);
        if (empty($param['basic']['id'])) {
            //生成唯一code
            $param['basic']['station_id'] = $this->gasCode();
        }
        $this->exists(!empty($param['basic']['id']))->save($param['basic']);
        if (empty($param['payment']['id']))
            $param['payment']['station_id'] = $this->id;
        app(StationPayment::class)->exists(!empty($param['payment']['id']))->save($param['payment']);
        $id = $this->id;
        $price = array_map(function ($item) use ($id) {
            if (empty($item['id'])) {
                $item['station_id'] = $id;
                $item['base_start_time'] = date("Y-m-d H:i:s");
            }
            return $item;
        }, $param['product']);
        app(StationPrice::class)->saveAll($price);
        $this->commit();
        return $this->toArray();
    }

    public function search(): array
    {
        return $this->where('state', 1)->column("id,name");
    }

    public function pageData(): array
    {
        $param = request()->param();
        //{page: 1,name:'',opt_id:'',station_id:'',state:'',province_id:'',city_id: '',mer_id:'',brand: '',commsion:'',is_height:'',is_test:'',payment:'',card_type:'',station_add_type:''}
        $data = $this->with(['mer', 'operation', 'ser', 'brand', 'stationTyp', 'stationTip'])->when(!empty($param['name']), function ($query) use ($param) {
            $query->where('name', 'like', "%{$param['name']}%");
        })->when(!empty($param['opt_id']), function ($query) use ($param) {
            $query->where('opt_id', $param['opt_id']);
        })->when(!empty($param['station_id']), function ($query) use ($param) {
            $query->where('station_id', $param['station_id']);
        })->when(!empty($param['state']), function ($query) use ($param) {
            $query->where('state', $param['state']);
        })->when(!empty($param['province_id']), function ($query) use ($param) {
            $query->where('province_id', $param['province_id']);
        })->when(!empty($param['city_id']), function ($query) use ($param) {
            $query->where('city_id', $param['city_id']);
        })->when(!empty($param['mer_id']), function ($query) use ($param) {
            $query->where('mer_id', $param['mer_id']);
        })->when(!empty($param['brand']), function ($query) use ($param) {
            $query->where('brand', $param['brand']);
        })->when(isset($param['commsion']) && $param['commsion'] >= 0, function ($query) use ($param) {
            $query->where('commsion', $param['commsion']);
        })->when(!empty($param['is_height']), function ($query) use ($param) {
            $query->where('is_height', $param['is_height']);
        })->when(!empty($param['is_test']), function ($query) use ($param) {
            $query->where('is_test', $param['is_test']);
        })->when(!empty($param['payment']) || !empty($param['card_type']) || !empty($param['station_add_type']), function ($query) use ($param) {
            $id = StationPayment::when(!empty($param['payment']), function ($q) use ($param) {
                $q->where('payment_type', $param['payment']);
            })->when(!empty($param['card_type']), function ($q) use ($param) {
                $q->where('card_type', $param['card_type']);
            })->when(!empty($param['station_add_type']), function ($q) use ($param) {
                $q->where('station_add_type', $param['station_add_type']);
            })->column("station_id");
            $query->whereIn('id', $id);
        })->order('create_time', 'desc')->paginate(['list_rows' => 30, 'page' => $param['page'] ?? 1])->toArray();
        return pageData($data);
    }

    private function gasCode(): string
    {
        $code = Str::random(6, 9);
        if ($this->where('station_id', $code)->count()) {
            return $this->gasCode();
        }
        return $code;
    }

    public function mer(): HasOne
    {
        return $this->hasOne(\app\model\Merchant::class, 'id', 'mer_id');
    }

    public function operation(): HasOne
    {
        return $this->hasOne(\app\model\StationOperation::class, 'id', 'opt_id');
    }

    public function ser(): HasOne
    {
        return $this->hasOne(\app\model\MerchantService::class, 'id', 'ser_id');
    }

    public function brand(): HasOne
    {
        return $this->hasOne(\app\model\StationBrand::class, 'id', 'brand');
    }

    public function stationTyp(): HasOne
    {
        return $this->hasOne(\app\model\StationType::class, 'id', 'station_type');
    }

    public function stationTip(): HasOne
    {
        return $this->hasOne(\app\model\Tips::class, 'id', 'station_tip');
    }

    public function payment(): HasOne
    {
        return $this->hasOne(\app\model\StationPayment::class, 'station_id');
    }

    public function product(): HasMany
    {
        return $this->hasMany(StationPrice::class, "station_id");
    }

    public function add_balance()
    {
        $param = request()->post();
        $data = $this->where('id', $param['id'])->where('state', 1)->find();
        if (empty($data)) throw new \Exception('数据不存在');
        $old_balance = $data->balance;
        $account = request()->account;
        $this->startTrans();
        $data->inc('balance', $param['balance'])->save();
        //记录充值记录
        app(StationBalanceNotice::class)->save([
            "order_sn" => date("YmdHis") . Str::random(6, 1),
            "station_id" => $data->id,
            "content" => $param['remark'],
            "number" => $param['balance'],
            "type" => 1,
            "admin" => $account->name ?? $account->account ?? '',
            "old_balance" => $old_balance,
            "new_banlan" => $data->balance
        ]);
        $this->commit();
        return $data;
    }

    public function userStation()
    {
        $param = request()->param();
        $field = [
            's.id',
            's.name',
            's.address',
            's.lng',
            's.lat',
            'o.discount_price',
            'o.gun_price',
            'o.office_price',
            'o.oil_id'
        ];
        $location = false;
        $distanceExpression = null;
        if ((!empty($param['lat']) && !empty($param['lng'])) && (is_numeric($param['lat']) && is_numeric($param['lng']))) {
            // 构建距离表达式
            $distanceExpression = "ST_Distance_Sphere(s.address_location, ST_GeomFromText('POINT({$param['lng']} {$param['lat']})'))";
            $field[] = Db::raw("{$distanceExpression} AS distance");
            $location = true;
        }
        $user = request()->user ?? [];
        //获取机构特殊定价油站信息
        $supplierPrice = request()->supplierPrice ?? [];
        $stationsId = [];
//        $sup_id = $user['supplier'] ?? 0;
        $gas = 0;
        if (!empty($param['gas'])) {
            $gas = app(StationOilNumber::class)->where('name', $param['gas'])->value("id");
        }
        if ($gas > 0 && !empty($user['supplier']) && !empty($supplierPrice)) {
            $stationsId = $supplierPrice[$gas][$user['supplier']] ?? [];
//            dd($supplierPrice[$gas],$stationsId);
        }
        $radius = 5000;
        if (!empty($param['distance']))
            $radius = $param['distance'] != 'all' ? $param['distance'] * 1000 : 0;
        $radiusCondition = null;
        if ($location && isset($radius) && $radius > 0) {
            $radiusCondition = ("$distanceExpression < {$radius}");
        }
        $order = $location ? "distance ASC" : 's.create_time DESC';
        if ($param['sort'] == 1) {
            $order = "distance ASC";
        } elseif ($param['sort'] == 2) {
            $order = "distance DESC";
        } elseif ($param['sort'] == 3) {
            $order = "o.price_discount DESC";
        } elseif ($param['sort'] == 4) {
            $order = "o.price_discount ASC";
        }
        $station = $this->alias('s')->join('station_price o', 'o.station_id=s.id')->where("o.sup_id", 0)->when(!empty($gas) && $gas > 0, function ($query) use ($gas) {
            $query->whereIn("o.oil_id", $gas);
        })->when(!empty($param['name']), function ($query) use ($param) {
            $query->where('s.name', 'like', '%' . $param['name'] . '%');
        })->when($radiusCondition, function ($query) use ($radiusCondition) {
            $query->whereRaw($radiusCondition);
        })->field($field)->orderRaw($order)->paginate()->toArray();

        if (!empty($station['data'])) {
            foreach ($station['data'] as &$value) {
                $value['distance'] = (float)bcdiv($value['distance'] ?? 0, 1000, 2);
                if (!empty($stationsId[$value['id']])) {
                    $value = array_merge($value, $stationsId[$value['id']]);
                }
            }
        }
        return $station;
    }
}
